function mxSpaceManager(graph, shiftRightwards, shiftDownwards, extendParents)
{
	var self = this;
	this.resizeHandler = function(sender, evt)
	{
		if (self.isEnabled())
		{
			self.cellsResized(evt.getArgAt(0));
		}
	};
	this.foldHandler = function(sender, evt)
	{
		if (self.isEnabled())
		{
			self.cellsResized(evt.getArgAt(2));
		}
	};
	this.shiftRightwards = (shiftRightwards != null) ? shiftRightwards : true;
	this.shiftDownwards = (shiftDownwards != null) ? shiftDownwards : true;
	this.extendParents = (extendParents != null) ? extendParents : true;
	this.setGraph(graph);
};
mxSpaceManager.prototype = new mxEventSource();
mxSpaceManager.prototype.constructor = mxSpaceManager;
mxSpaceManager.prototype.graph = null;
mxSpaceManager.prototype.enabled = true;
mxSpaceManager.prototype.shiftRightwards = true;
mxSpaceManager.prototype.shiftDownwards = true;
mxSpaceManager.prototype.extendParents = true;
mxSpaceManager.prototype.resizeHandler = null;
mxSpaceManager.prototype.foldHandler = null;
mxSpaceManager.prototype.isCellIgnored = function(cell)
{
	return !this.getGraph().getModel().isVertex(cell);
};
mxSpaceManager.prototype.isCellShiftable = function(cell)
{
	return this.getGraph().getModel().isVertex(cell) && this.getGraph().isCellMovable(cell);
};
mxSpaceManager.prototype.isEnabled = function()
{
	return this.enabled;
};
mxSpaceManager.prototype.setEnabled = function(value)
{
	this.enabled = value;
};
mxSpaceManager.prototype.isShiftRightwards = function()
{
	return this.shiftRightwards;
};
mxSpaceManager.prototype.setShiftRightwards = function(value)
{
	this.shiftRightwards = value;
};
mxSpaceManager.prototype.isShiftDownwards = function()
{
	return this.shiftDownwards;
};
mxSpaceManager.prototype.setShiftDownwards = function(value)
{
	this.shiftDownwards = value;
};
mxSpaceManager.prototype.isExtendParents = function()
{
	return this.extendParents;
};
mxSpaceManager.prototype.setExtendParents = function(value)
{
	this.extendParents = value;
};
mxSpaceManager.prototype.getGraph = function()
{
	return this.graph;
};
mxSpaceManager.prototype.setGraph = function(graph)
{
	if (this.graph != null)
	{
		this.graph.removeListener(this.resizeHandler);
		this.graph.removeListener(this.foldHandler);
	}
	this.graph = graph;

	if (this.graph != null)
	{
		this.graph.addListener(mxEvent.RESIZE_CELLS, this.resizeHandler);
		this.graph.addListener(mxEvent.FOLD_CELLS, this.foldHandler);
	}
};
mxSpaceManager.prototype.cellsResized = function(cells)
{
	if (cells != null)
	{
		var model = this.graph.getModel();

		model.beginUpdate();

		try
		{
			for (var i = 0; i < cells.length; i++)
			{
				if (!this.isCellIgnored(cells[i]))
				{
					this.cellResized(cells[i]);
					break;
				}
			}
		}
		finally
		{
			model.endUpdate();
		}
	}
};
mxSpaceManager.prototype.cellResized = function(cell)
{
	var graph = this.getGraph();
	var view = graph.getView();
	var model = graph.getModel();
	var state = view.getState(cell);
	var pstate = view.getState(model.getParent(cell));

	if (state != null && pstate != null)
	{
		var cells = this.getCellsToShift(state);
		var geo = model.getGeometry(cell);

		if (cells != null && geo != null)
		{
			var tr = view.translate;
			var scale = view.scale;
			var x0 = state.x - pstate.origin.x - tr.x * scale;
			var y0 = state.y - pstate.origin.y - tr.y * scale;
			var right = state.x + state.width;
			var bottom = state.y + state.height;
			var dx = state.width - geo.width * scale + x0 - geo.x * scale;
			var dy = state.height - geo.height * scale + y0 - geo.y * scale;
			var fx = 1 - geo.width * scale / state.width;
			var fy = 1 - geo.height * scale / state.height;
			model.beginUpdate();

			try
			{
				for (var i = 0; i < cells.length; i++)
				{
					if (cells[i] != cell && this.isCellShiftable(cells[i]))
					{
						this.shiftCell(cells[i], dx, dy, x0, y0, right, bottom, fx, fy,
							this.isExtendParents() && graph.isExtendParent(cells[i]));
					}
				}
			}
			finally
			{
				model.endUpdate();
			}
		}
	}
};
mxSpaceManager.prototype.shiftCell = function(cell, dx, dy, Ox0, y0, right, bottom, fx, fy, extendParent)
{
	var graph = this.getGraph();
	var state = graph.getView().getState(cell);

	if (state != null)
	{
		var model = graph.getModel();
		var geo = model.getGeometry(cell);

		if (geo != null)
		{
			model.beginUpdate();

			try
			{
				if (this.isShiftRightwards())
				{
					if (state.x >= right)
					{
						geo = geo.translate(-dx, 0);
					}
					else
					{
						var tmpDx = Math.max(0, state.x - x0);
						geo = geo.translate(-fx * tmpDx, 0);
					}
				}

				if (this.isShiftDownwards())
				{
					if (state.y >= bottom)
					{
						geo = geo.translate(0, -dy);
					}
					else
					{
						var tmpDy = Math.max(0, state.y - y0);
						geo = geo.translate(0, -fy * tmpDy);
					}

					if (geo != model.getGeometry(cell))
					{
						model.setGeometry(cell, geo);

						if (extendParent)
						{
							graph.extendParent(cell);
						}
					}
				}
			}
			finally
			{
				model.endUpdate();
			}
		}
	}
};
mxSpaceManager.prototype.getCellsToShift = function(state)
{
	var graph = this.getGraph();
	var parent = graph.getModel().getParent(state.cell);
	var down = this.isShiftDownwards();
	var right = this.isShiftRightwards();
	return graph.getCellsBeyond(state.x + ((down) ? 0 : state.width), state.y + ((down && right) ? 0 : state.height),
		parent, right, down);
};
mxSpaceManager.prototype.destroy = function()
{
	this.setGraph(null);
};